package com.bac.rentmap.ad.flat.crawler.irrby.proccess;

import java.io.IOException;
import java.util.logging.Logger;

import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;
import org.springframework.beans.factory.annotation.Required;

import com.bac.rentmap.ad.crawler.phone.PhoneNormalizer;
import com.bac.rentmap.ad.crawler.support.CrawlingSupport;
import com.bac.rentmap.ad.flat.crawler.FlatCrawledAd;
import com.bac.rentmap.ad.flat.crawler.ParsingHelper;

public class IrrBySecondaryCrawler extends CrawlingSupport<FlatCrawledAd> {
    private static final Logger log = Logger
            .getLogger(IrrBySecondaryCrawler.class.getName());
    private static final String XPATH_PREFIX = "//body/div/div/div/div[@class=\"left-colCat\"]/";

    private ParsingHelper parsingHelper;

    private PhoneNormalizer phoneNormalizer;

    public void updateFlatCrawledAd(FlatCrawledAd flatCrawledAd)
            throws IOException {
        crawl(flatCrawledAd.getSourceUrl(), flatCrawledAd);
    }

    @Override
    protected FlatCrawledAd parseRootTagNode(TagNode rootNode,
            FlatCrawledAd flatCrawledAd) throws XPatherException {
        Object[] objects = rootNode.evaluateXPath(XPATH_PREFIX
                + "div/div[@class=\"details-col\"]");

        if (objects.length == 0)
            throw new NotEnoughDataException("Can't parse ANY data for "
                    + flatCrawledAd + ". It seems link is outdated");
        TagNode tagNode = (TagNode) objects[0];

        try {
            String header = getValue(rootNode, XPATH_PREFIX
                    + "div/div/div/div[@class=\"pad-block\"][1]/text()");

            String description = null;
            try {
                description = parseDescription(rootNode);
                flatCrawledAd.setDescription(description);
            } catch (IllegalArgumentException e) {
                log.fine("Description not parsed from body because " + e
                        + ", using header for description");
                flatCrawledAd.setDescription(header);
            }
            parseStreetAndBuilding(header, description, tagNode, flatCrawledAd);
            String phone = parsePhone(rootNode, description, header);
            flatCrawledAd.setPhone(phoneNormalizer.normalizePhone(phone));
            flatCrawledAd.setRoom(parseRoom(header, tagNode));
            flatCrawledAd.setReadyForTransformation(Boolean.TRUE);
            return flatCrawledAd;
        } catch (IllegalArgumentException e) {
            throw new NotEnoughDataException(e);
        }
    }

    private void parseStreetAndBuilding(String header, String description,
            TagNode tagNode, FlatCrawledAd flatCrawledAd)
            throws XPatherException {
        String streetAndBuilding = null;
        try {
            streetAndBuilding = getValue(tagNode,
                    "div/div/table/tbody/tr/[td[1]/text()='Улица:']/td[2]/text()");
            log.fine("Parsed address: " + streetAndBuilding);
            parsingHelper.parseStreetAndBuilding(streetAndBuilding,
                    flatCrawledAd);
        } catch (IllegalArgumentException e) {
            log.fine("Can't parse street and building from page "
                    + streetAndBuilding);
        }
        parsingHelper.mayBeParseStreetAndBuilding(header, description,
                flatCrawledAd);
    }

    private String parseDescription(TagNode tagNode) throws XPatherException {
        String res = getValue(
                tagNode,
                XPATH_PREFIX
                        + "div/div/div/div/[div/strong/text()='Текст объявления']/p/text()");
        log.fine("Parsed description: " + res);
        return res;
    }

    private String parseRoom(String header, TagNode tagNode)
            throws XPatherException {
        try {
            return getValue(tagNode,
                    "div/div/table/tbody/tr/[td[1]/text()='Количество комнат:']/td[2]/text()");
        } catch (IllegalArgumentException e) {
            return parsingHelper.parseRoom(header);
        }
    }

    private String parsePhone(TagNode tagNode, String description, String header)
            throws XPatherException {
        String[] phoneXpathes = { "/*[@class=\"ico-phone\"]/text()",
                "/*[@class=\"pseller_mphone\"]/text()",
                "/*[@class=\"ico-mphone\"]/text()" };
        for (String phoneXpath : phoneXpathes) {
            try {
                String phoneString = getValue(tagNode, XPATH_PREFIX
                        + phoneXpath);
                log.fine("Parsed phone: " + phoneString);
                phoneString = parsingHelper.parsePhone(ParsingHelper
                        .convertHtml2text(phoneString));
                return phoneString;
            } catch (IllegalArgumentException e) {
            }
        }
        // TODO: try parse phone from description or header
        throw new NotEnoughDataException("Can't parse phone");
    }

    @Required
    public void setParsingHelper(ParsingHelper parsingHelper) {
        this.parsingHelper = parsingHelper;
    }

    @Required
    public void setPhoneNormalizer(PhoneNormalizer phoneNormalizer) {
        this.phoneNormalizer = phoneNormalizer;
    }
}
